From 51b9f53d044c0ded83de7274a5adc7e1ccb286e3 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk" Date: Thu, 28 Apr 2005 20:50:48 +0000 Subject: [PATCH] bitkeeper revision 1.1389.2.2 (42714ca83Gv7CX98R4gC0TU3w-pX1Q) Merge xen-2.0-testing "sync w/ unstable" changes. --- .rootkeys | 2 + .../arch/xen/kernel/gnttab.c | 391 ++++++++++++++++++ .../include/asm-xen/gnttab.h | 72 ++++ 3 files changed, 465 insertions(+) create mode 100644 linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c create mode 100644 linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h diff --git a/.rootkeys b/.rootkeys index bfec964108..701263e1f8 100644 --- a/.rootkeys +++ b/.rootkeys @@ -259,6 +259,7 @@ 41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.11-xen-sparse/arch/xen/kernel/devmem.c 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.11-xen-sparse/arch/xen/kernel/fixup.c +412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c 40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c 414c113396tK1HTVeUalm3u-1DF16g linux-2.6.11-xen-sparse/arch/xen/kernel/skbuff.c 418f90e4lGdeJK9rmbOB1kN-IKSjsQ linux-2.6.11-xen-sparse/arch/xen/kernel/smp.c @@ -406,6 +407,7 @@ 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.11-xen-sparse/include/asm-xen/ctrl_if.h 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.11-xen-sparse/include/asm-xen/evtchn.h 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.11-xen-sparse/include/asm-xen/foreign_page.h +412dfaeazclyNDM0cpnp60Yo4xulpQ linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h 40f5623aGPlsm0u1LTO-NVZ6AGzNRQ linux-2.6.11-xen-sparse/include/asm-xen/hypervisor.h 3f108af1ylCIm82H052FVTfXACBHrw linux-2.6.11-xen-sparse/include/asm-xen/linux-public/privcmd.h 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6.11-xen-sparse/include/asm-xen/linux-public/suspend.h diff --git a/linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c b/linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c new file mode 100644 index 0000000000..0ae2ac6548 --- /dev/null +++ b/linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c @@ -0,0 +1,391 @@ +/****************************************************************************** + * gnttab.c + * + * Two sets of functionality: + * 1. Granting foreign access to our memory reservation. + * 2. Accessing others' memory reservations via grant references. + * (i.e., mechanisms for both sender and recipient of grant references) + * + * Copyright (c) 2005, Christopher Clark + * Copyright (c) 2004, K A Fraser + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef set_fixmap_ma +#define set_fixmap_ma set_fixmap +#endif + +#if 1 +#define ASSERT(_p) \ + if ( !(_p) ) { printk(KERN_ALERT"Assertion '%s': line %d, file %s\n", \ + #_p , __LINE__, __FILE__); *(int*)0=0; } +#else +#define ASSERT(_p) ((void)0) +#endif + +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "xen_grant: " fmt, ##args) + + +EXPORT_SYMBOL(gnttab_grant_foreign_access); +EXPORT_SYMBOL(gnttab_end_foreign_access); +EXPORT_SYMBOL(gnttab_query_foreign_access); +EXPORT_SYMBOL(gnttab_grant_foreign_transfer); +EXPORT_SYMBOL(gnttab_end_foreign_transfer); +EXPORT_SYMBOL(gnttab_alloc_grant_references); +EXPORT_SYMBOL(gnttab_free_grant_references); +EXPORT_SYMBOL(gnttab_claim_grant_reference); +EXPORT_SYMBOL(gnttab_release_grant_reference); +EXPORT_SYMBOL(gnttab_grant_foreign_access_ref); +EXPORT_SYMBOL(gnttab_grant_foreign_transfer_ref); + +static grant_ref_t gnttab_free_list[NR_GRANT_ENTRIES]; +static grant_ref_t gnttab_free_head; + +static grant_entry_t *shared; + +/* + * Lock-free grant-entry allocator + */ + +static inline int +get_free_entry( + void) +{ + grant_ref_t fh, nfh = gnttab_free_head; + do { if ( unlikely((fh = nfh) == NR_GRANT_ENTRIES) ) return -1; } + while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, + gnttab_free_list[fh])) != fh) ); + return fh; +} + +static inline void +put_free_entry( + grant_ref_t ref) +{ + grant_ref_t fh, nfh = gnttab_free_head; + do { gnttab_free_list[ref] = fh = nfh; wmb(); } + while ( unlikely((nfh = cmpxchg(&gnttab_free_head, fh, ref)) != fh) ); +} + +/* + * Public grant-issuing interface functions + */ + +int +gnttab_grant_foreign_access( + domid_t domid, unsigned long frame, int readonly) +{ + int ref; + + if ( unlikely((ref = get_free_entry()) == -1) ) + return -ENOSPC; + + shared[ref].frame = frame; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); + + return ref; +} + +void +gnttab_grant_foreign_access_ref( + grant_ref_t ref, domid_t domid, unsigned long frame, int readonly) +{ + shared[ref].frame = frame; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_permit_access | (readonly ? GTF_readonly : 0); +} + + +int +gnttab_query_foreign_access( grant_ref_t ref ) +{ + u16 nflags; + + nflags = shared[ref].flags; + + return ( nflags & (GTF_reading|GTF_writing) ); +} + +void +gnttab_end_foreign_access( grant_ref_t ref, int readonly ) +{ + u16 flags, nflags; + + nflags = shared[ref].flags; + do { + if ( (flags = nflags) & (GTF_reading|GTF_writing) ) + printk(KERN_ALERT "WARNING: g.e. still in use!\n"); + } + while ( (nflags = cmpxchg(&shared[ref].flags, flags, 0)) != flags ); + + put_free_entry(ref); +} + +int +gnttab_grant_foreign_transfer( + domid_t domid, unsigned long pfn ) +{ + int ref; + + if ( unlikely((ref = get_free_entry()) == -1) ) + return -ENOSPC; + + shared[ref].frame = pfn; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_accept_transfer; + + return ref; +} + +void +gnttab_grant_foreign_transfer_ref( + grant_ref_t ref, domid_t domid, unsigned long pfn ) +{ + shared[ref].frame = pfn; + shared[ref].domid = domid; + wmb(); + shared[ref].flags = GTF_accept_transfer; +} + +unsigned long +gnttab_end_foreign_transfer( + grant_ref_t ref) +{ + unsigned long frame = 0; + u16 flags; + + flags = shared[ref].flags; + ASSERT(flags == (GTF_accept_transfer | GTF_transfer_committed)); + + /* + * If a transfer is committed then wait for the frame address to appear. + * Otherwise invalidate the grant entry against future use. + */ + if ( likely(flags != GTF_accept_transfer) || + (cmpxchg(&shared[ref].flags, flags, 0) != GTF_accept_transfer) ) + while ( unlikely((frame = shared[ref].frame) == 0) ) + cpu_relax(); + + put_free_entry(ref); + + return frame; +} + +void +gnttab_free_grant_references( u16 count, grant_ref_t head ) +{ + /* TODO: O(N)...? */ + grant_ref_t to_die = 0, next = head; + int i; + + for ( i = 0; i < count; i++ ) + to_die = next; + next = gnttab_free_list[next]; + put_free_entry( to_die ); +} + +int +gnttab_alloc_grant_references( u16 count, + grant_ref_t *head, + grant_ref_t *terminal ) +{ + int i; + grant_ref_t h = gnttab_free_head; + + for ( i = 0; i < count; i++ ) + if ( unlikely(get_free_entry() == -1) ) + goto not_enough_refs; + + *head = h; + *terminal = gnttab_free_head; + + return 0; + +not_enough_refs: + gnttab_free_head = h; + return -ENOSPC; +} + +int +gnttab_claim_grant_reference( grant_ref_t *private_head, + grant_ref_t terminal ) +{ + grant_ref_t g; + if ( unlikely((g = *private_head) == terminal) ) + return -ENOSPC; + *private_head = gnttab_free_list[g]; + return g; +} + +void +gnttab_release_grant_reference( grant_ref_t *private_head, + grant_ref_t release ) +{ + gnttab_free_list[release] = *private_head; + *private_head = release; +} + +/* + * ProcFS operations + */ + +#ifdef CONFIG_PROC_FS + +static struct proc_dir_entry *grant_pde; + +static int grant_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long data) +{ + int ret; + privcmd_hypercall_t hypercall; + + /* XXX Need safety checks here if using for anything other + * than debugging */ + return -ENOSYS; + + if ( cmd != IOCTL_PRIVCMD_HYPERCALL ) + return -ENOSYS; + + if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) ) + return -EFAULT; + + if ( hypercall.op != __HYPERVISOR_grant_table_op ) + return -ENOSYS; + + /* hypercall-invoking asm taken from privcmd.c */ + __asm__ __volatile__ ( + "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; " + "movl 4(%%eax),%%ebx ;" + "movl 8(%%eax),%%ecx ;" + "movl 12(%%eax),%%edx ;" + "movl 16(%%eax),%%esi ;" + "movl 20(%%eax),%%edi ;" + "movl (%%eax),%%eax ;" + TRAP_INSTR "; " + "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx" + : "=a" (ret) : "0" (&hypercall) : "memory" ); + + return ret; +} + +static struct file_operations grant_file_ops = { + ioctl: grant_ioctl, +}; + +static int grant_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + unsigned int i; + grant_entry_t *gt; + + gt = (grant_entry_t *)shared; + len = 0; + + for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) + /* TODO: safety catch here until this can handle >PAGE_SIZE output */ + if (len > (PAGE_SIZE - 200)) + { + len += sprintf( page + len, "Truncated.\n"); + break; + } + + if ( gt[i].flags ) + len += sprintf( page + len, + "Grant: ref (0x%x) flags (0x%hx) dom (0x%hx) frame (0x%x)\n", + i, + gt[i].flags, + gt[i].domid, + gt[i].frame ); + + *eof = 1; + return len; +} + +static int grant_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + /* TODO: implement this */ + return -ENOSYS; +} + +#endif /* CONFIG_PROC_FS */ + +int gnttab_resume(void) +{ + gnttab_setup_table_t setup; + unsigned long frames[NR_GRANT_FRAMES]; + int i; + + setup.dom = DOMID_SELF; + setup.nr_frames = NR_GRANT_FRAMES; + setup.frame_list = frames; + + BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_setup_table, &setup, 1) != 0); + BUG_ON(setup.status != 0); + + for ( i = 0; i < NR_GRANT_FRAMES; i++ ) + set_fixmap_ma(FIX_GNTTAB_END - i, frames[i] << PAGE_SHIFT); + + return 0; +} + +int gnttab_suspend(void) +{ + int i; + + for ( i = 0; i < NR_GRANT_FRAMES; i++ ) + clear_fixmap(FIX_GNTTAB_END - i); + + return 0; +} + +static int __init gnttab_init(void) +{ + int i; + + BUG_ON(gnttab_resume()); + + shared = (grant_entry_t *)fix_to_virt(FIX_GNTTAB_END); + + for ( i = 0; i < NR_GRANT_ENTRIES; i++ ) + gnttab_free_list[i] = i + 1; + +#ifdef CONFIG_PROC_FS + /* + * /proc/xen/grant : used by libxc to access grant tables + */ + if ( (grant_pde = create_xen_proc_entry("grant", 0600)) == NULL ) + { + WPRINTK("Unable to create grant xen proc entry\n"); + return -1; + } + + grant_file_ops.read = grant_pde->proc_fops->read; + grant_file_ops.write = grant_pde->proc_fops->write; + + grant_pde->proc_fops = &grant_file_ops; + + grant_pde->read_proc = &grant_read; + grant_pde->write_proc = &grant_write; +#endif + + printk("Grant table initialized\n"); + return 0; +} + +__initcall(gnttab_init); diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h b/linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h new file mode 100644 index 0000000000..642a74dbf9 --- /dev/null +++ b/linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * gnttab.h + * + * Two sets of functionality: + * 1. Granting foreign access to our memory reservation. + * 2. Accessing others' memory reservations via grant references. + * (i.e., mechanisms for both sender and recipient of grant references) + * + * Copyright (c) 2004, K A Fraser + * Copyright (c) 2005, Christopher Clark + */ + +#ifndef __ASM_GNTTAB_H__ +#define __ASM_GNTTAB_H__ + +#include +#include +#include + +/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ +#define NR_GRANT_FRAMES 4 +#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) + +int +gnttab_grant_foreign_access( + domid_t domid, unsigned long frame, int readonly); + +void +gnttab_end_foreign_access( + grant_ref_t ref, int readonly); + +int +gnttab_grant_foreign_transfer( + domid_t domid, unsigned long pfn); + +unsigned long +gnttab_end_foreign_transfer( + grant_ref_t ref); + +int +gnttab_query_foreign_access( + grant_ref_t ref ); + +/* + * operations on reserved batches of grant references + */ +int +gnttab_alloc_grant_references( + u16 count, grant_ref_t *pprivate_head, grant_ref_t *private_terminal ); + +void +gnttab_free_grant_references( + u16 count, grant_ref_t private_head ); + +int +gnttab_claim_grant_reference( grant_ref_t *pprivate_head, grant_ref_t terminal +); + +void +gnttab_release_grant_reference( + grant_ref_t *private_head, grant_ref_t release ); + +void +gnttab_grant_foreign_access_ref( + grant_ref_t ref, domid_t domid, unsigned long frame, int readonly); + +void +gnttab_grant_foreign_transfer_ref( + grant_ref_t, domid_t domid, unsigned long pfn); + + +#endif /* __ASM_GNTTAB_H__ */ -- 2.30.2